-- ======================================================================
-- Hell Lua Bus
--
-- Copyright 2012-2013Hell-Prototypes
--
-- http://www.hellprototypes.com/
--
-- This is free software, licensed under the terms of the GNU General
-- Public License as published by the Free Software Foundation.
-- ======================================================================
hlb = require('libhlb')
printf = require "mod_print"
iHEX = require "mod_iHEX"

SIM_DEBUG = false

function device_open()
	local ret = hlb.usb_open(0x6666f0f3)
	if ret < 0 then
		print("Fail to open usb device: " .. ret)
		return false
	end

	return true
end

function device_close()
	local ret = hlb.usb_close()
	if ret < 0 then
		print("Fail to close usb device")
		return false
	end

	return true
end

function pause()
    io.write("\r\nAny key to continue ...")
    io.flush()
    io.read()
    print("")
end
-- -----------------------------------------------
function Read_dot_File(file_name)
	-- print("file_name: " .. file_name)
	local file = io.open(file_name, "r")

	local raw_data = {}
	local data = 0
	local line_num = 1

	for line in file:lines() do
		for i=1, line:len()/5 do
			 data = tonumber(line:sub(5 * i - 2 , 5 * i-1), 16)
			 if type(data) == "number" then
			 	raw_data[#raw_data + 1] = data
			 else
			 	print("Error to convert line: " .. line_num .. " of: " .. line:sub(5 * i - 2 , 5 * i-1) )
			 end
		end
		line_num = line_num + 1
	end

	file:close()

	return raw_data
end
-- -----------------------------------------------
function split_to_3byte(addr)
	local B2 = bit32.band(bit32.rshift(addr, 16), 0xFF)
	local B1 = bit32.band(bit32.rshift(addr, 8),  0xFF)
	local B0 = bit32.band(addr, 0xFF)

    return B2, B1, B0
end
-- -----------------------------------------------
function string_to_table(str)
    local tb = {}
    local index = 1
    for i=1, string.len(str) do
        tb [i] = string.byte(str, i)
    end
    return tb
end

REQ_ERASE_APP		=0xC0
REQ_LOAD_BUFF		=0xC1
REQ_WR_PAGE		    =0xC2
REQ_READ_FLASH		=0xC3
REQ_READ_CALIB		=0xC4

REQ_BOOT_APP		=0xD0

USB_MAX_DATA_LEN    = 64
-- -----------------------------------------------
function usb_ctrl_cmd(req, cmd, value)
    local msg
    local ret
    local val
    local len

    if value then
        val = value
    else
        val = 0
    end
    if cmd then
        len = #cmd
        if #cmd > 64 then
            print("usb_ctrl_cmd() fail: cmd len error" .. #rom_cmd)
        return false
    end
    else
        len = 0
    end

    msg = {0x40, req, val, 0, len, 500}

    if cmd then
        ret = hlb.usb_control_msg(cmd, msg)
    else
        ret = hlb.usb_control_msg(msg)
    end
    if ret < 0 then
        print("usb_ctrl_cmd() ret = " .. ret)
        return false
    end
    return true
end

function app_erase_app()
    return usb_ctrl_cmd(REQ_ERASE_APP)
end

function app_load_buffer(buf_data)
    local index = 1
    local cmd_data = {}

    if #buf_data > 256 then
        return false
    end
    while index <= #buf_data do
        for i=1, 64 do
            cmd_data[i] = buf_data[index]
            index = index + 1
            if index > #buf_data then
                break
            end
        end

        if usb_ctrl_cmd(REQ_LOAD_BUFF, cmd_data) == false then
            return false
        end
        cmd_data = {}
    end
    return true
end
function app_write_page(addr)
    local cmd={}

    return usb_ctrl_cmd(REQ_WR_PAGE, cmd, addr)
end
function app_read_flash(address, read_len)
    if SIM_DEBUG == true then
        local ret = {}
        for i=1, read_len do
            ret[i] = i;
        end
        return ret
    end

    local msg = {0x40+0x80, REQ_READ_FLASH, address, 0, read_len, 500}
    local ret
    local empty = {}
    if read_len > 64 then
        return empty
    end
    ret = hlb.usb_control_msg(msg)
    if(type(ret) == "table") then
        return ret
    else
        print("rom_read_feedback() fail")
    end
    return empty
end

-- -----------------------------------------------
function app_read_app(start_addr, len)
    local index = 1
    local read_back = {}
    local read_len
    local addr = start_addr
    local buffer = {}

    print("App Reading ...")
    while(index <= len) do
        if len - index >= 64 then
            read_len = 64
        else
            read_len = len - index + 1
        end
        read_back = app_read_flash(addr, read_len)

        addr = addr + read_len
        if #read_back ~= read_len then
            read_back = {}
            return read_back
        end
        for i=1, #read_back do
            buffer[index] = read_back[i]
            index = index + 1
        end
        io.write(".")
    end

    print("\r\n")
    return buffer
end
-- -----------------------------------------------

ret = device_open()
if ret == false then
    print("device_open fail")
    return
end

local start_addr
local pgm_data

start_addr, pgm_data = iHEX.Read_File("hwatch_debug1.hex")
printf.table(pgm_data, true)

--=========================
if app_erase_app() == true then
    local index = 1
    local address = start_addr
    local page_data = {}

    print("ROM Programing ... len: " .. #pgm_data)
    while index <= #pgm_data do
        for i=1, 256 do
            page_data[i] = pgm_data[index]
            index = index + 1
            if index > #pgm_data then
                break
            end
        end
        io.write(".")

        if app_load_buffer(page_data) == false then
            print("app_load_buffer() FAIL， address = " ..address.. "\r\n")
            device_close()
            return false
        end
        if app_write_page(address) == false then
            print("app_write_page() FAIL， address = " ..address.. "\r\n")
            device_close()
            return false
        end
        address = address + #page_data
        page_data = {}
    end
    print("\r\n")
    local app_rb = app_read_app(start_addr, #pgm_data)
    printf.table(app_rb, true)

    --boot app
    usb_ctrl_cmd(REQ_BOOT_APP)
end

-- -----------------------------------------------
device_close()
